Skip to content

fix: return no-op for stale review_id 404 in dismiss_pull_request_review - #49745

Merged
pelikhan merged 5 commits into
mainfrom
copilot/aw-failures-dismiss-pull-request-review
Aug 2, 2026
Merged

fix: return no-op for stale review_id 404 in dismiss_pull_request_review#49745
pelikhan merged 5 commits into
mainfrom
copilot/aw-failures-dismiss-pull-request-review

Conversation

Copilot AI commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

A dismiss_pull_request_review message targeting a review that no longer exists causes pulls.getReview to 404, which propagates as a fatal error and fails the entire safe_outputs job — blocking unrelated safe outputs in the same run.

Changes

  • dismiss_pull_request_review.cjs — wrap the pulls.getReview call in a targeted try/catch; on 404 return { success: true, skipped: true, reason: "review no longer exists" } instead of surfacing a hard failure. Non-404 errors are re-thrown to the outer catch as before.
try {
  const { data } = await githubClient.rest.pulls.getReview({ ... });
  review = data;
} catch (getReviewError) {
  if (getReviewError?.status === 404) {
    return { success: true, skipped: true, reason: "review no longer exists", review_id: reviewId, ... };
  }
  throw getReviewError;
}
  • dismiss_pull_request_review.test.cjs — regression test for the explicit review_id + 404 path: asserts success: true, skipped: true, and that dismissReview is never called.

Design note

This mirrors the stale-thread no-op pattern in resolve_pr_review_thread.cjs. dismiss_pull_request_review is intentionally not added to REPORT_ONLY_FAILURE_TYPES — legitimate failures (e.g. author mismatch) should remain fatal.


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 15.2 AIC · ⌖ 8.57 AIC · ⊞ 8.2K ·
Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 31.4 AIC · ⌖ 8.75 AIC · ⊞ 8.3K ·
Comment /souschef to run again

When `pulls.getReview` returns 404 for an explicit `review_id`, the
review is already dismissed or deleted (stale ID). Instead of hard-failing
the safe_outputs job, return `{success: true, skipped: true}` as a no-op,
mirroring the stale-thread pattern used in resolve_pr_review_thread.

Also adds a regression test covering the 404 path on explicit review_id.

Fixes: stale review ID hard-failing the safe_outputs job on PR Sous Chef
runs (run 30731801766).

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add dismiss_pull_request_review to safe-outputs failure set fix: return no-op for stale review_id 404 in dismiss_pull_request_review Aug 2, 2026
Copilot AI requested a review from pelikhan August 2, 2026 10:34
@pelikhan
pelikhan marked this pull request as ready for review August 2, 2026 10:45
Copilot AI review requested due to automatic review settings August 2, 2026 10:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Handles stale pull-request review IDs as non-fatal no-ops, preventing unrelated safe outputs from failing.

Changes:

  • Converts getReview 404 responses into successful skipped results.
  • Adds regression coverage ensuring dismissal is not attempted.
Show a summary per file
File Description
actions/setup/js/dismiss_pull_request_review.cjs Handles stale review IDs safely.
actions/setup/js/dismiss_pull_request_review.test.cjs Tests the explicit review-ID 404 path.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Balanced

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #49745 does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold: 100).

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — approving with one minor suggestion.

📋 Key Themes & Highlights

Key Themes

  • Root cause addressed: The fix correctly handles the 404 case at the right level (getReview), not by swallowing the error broadly — non-404 errors still re-throw.
  • Pattern consistency: Mirrors the existing stale-thread no-op in resolve_pr_review_thread.cjs.
  • Regression test included: A focused test covers the new path with the correct mock setup.

Minor Suggestion

  • The test asserts review_id but omits pull_request_number and repo — full contract coverage would prevent silent shape regressions (see inline comment).

Positive Highlights

  • ✅ Targeted try/catch scope — only the getReview call is wrapped, not the broader dismiss flow
  • ✅ Non-404 errors are correctly re-thrown
  • dismissReview not-called assertion is a good guard
  • ✅ Clear PR description with a design rationale note

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 18.8 AIC · ⌖ 7.95 AIC · ⊞ 7.1K
Comment /matt to run again

expect(result.review_id).toBe(123);
expect(mockDismissReview).not.toHaveBeenCalled();
});
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The test doesn't assert pull_request_number or repo fields on the returned no-op — these are part of the documented return shape and missing assertions allow silent regressions if the structure changes.

💡 Suggested additions
expect(result.pull_request_number).toBeDefined();
expect(result.repo).toMatch(/\//);

All fields of the contract surface should be covered so a future refactor can't silently drop them.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6aa73e4. The 404 no-op regression now also asserts pull_request_number and repo in /home/runner/work/gh-aw/gh-aw/actions/setup/js/dismiss_pull_request_review.test.cjs so the full return shape stays covered.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 100/100 — Excellent

Analyzed 1 test(s): 1 design, 0 implementation, 0 violation(s).

📊 Metrics (1 test)
Metric Value
Analyzed 1 (Go: 0, JS: 1)
✅ Design 1 (100%)
⚠️ Implementation 0 (0%)
Edge/error coverage 1 (100%)
Duplicate clusters 0
Inflation No
🚨 Violations 0
Test File Classification Issues
returns skipped no-op when getReview returns 404 for an explicit review_id dismiss_pull_request_review.test.cjs:366 behavioral_contract, design_test, high_value None

Verdict

passed. 0% implementation tests (threshold: 30%). The new test directly covers the 404 error branch introduced in this fix, verifying the no-op return shape and confirming dismissReview is not called — strong behavioral coverage for a targeted bug fix.

🧪 Test quality analysis by Test Quality Sentinel · sonnet46 · 31.3 AIC · ⌖ 12.3 AIC · ⊞ 8.4K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 100/100. 0% implementation tests (threshold: 30%).

@github-actions github-actions Bot mentioned this pull request Aug 2, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix is correct and well-scoped. The targeted try/catch on pulls.getReview handles 404 gracefully by returning { success: true, skipped: true } without swallowing other errors, and the test confirms dismissReview is not called on stale review IDs.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 13.4 AIC · ⌖ 10.1 AIC · ⊞ 5.4K

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: Approve with minor suggestions

Correct, well-scoped fix; no blocking issues found.

💡 Themes
  • The 404-swallowing pattern mirrors the existing no-op approach in resolve_pr_review_thread.cjs and the error?.status === 404 check matches established conventions used elsewhere in this codebase (check_permissions_utils.cjs, checkout_pr_branch.cjs), so it is not a fragile one-off.
  • Two non-blocking suggestions posted: (1) enrich the re-thrown non-404 error with review/PR context for easier log triage, and (2) add a negative test asserting non-404 errors are not swallowed, to guard against future regressions that could widen the 404 check.
  • Correctly leaves dismiss_pull_request_review out of REPORT_ONLY_FAILURE_TYPES, keeping legitimate failures (e.g. author mismatch) fatal as intended.

🔎 Code quality review by PR Code Quality Reviewer · auto · 46.5 AIC · ⌖ 3.73 AIC · ⊞ 7.8K
Comment /review to run again

repo: `${owner}/${repo}`,
};
}
throw getReviewError;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-404 errors are re-thrown without added context, making them harder to diagnose in workflow logs when many reviews/PRs are processed.

💡 Details

When getReviewError.status is anything other than 404 (403, 500, rate-limit, network error), it propagates via throw getReviewError unchanged. The outer catch (error) at the bottom of main only records getErrorMessage(error), so the resulting failure message won't mention which review_id/pull_request_number the lookup was for. In a workflow that fans out over multiple dismiss requests, this makes triage harder.

Suggested fix:

} catch (getReviewError) {
  if (getReviewError?.status === 404) {
    return { success: true, skipped: true, reason: "review no longer exists", review_id: reviewId, pull_request_number: pullRequestNumber, repo: `${owner}/${repo}` };
  }
  getReviewError.message = `Failed to fetch review ${reviewId} on ${owner}/${repo}#${pullRequestNumber}: ${getReviewError.message}`;
  throw getReviewError;
}

Rationale: preserving the original error type/stack while enriching the message keeps the fatal-failure behavior intact but makes logs actionable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6aa73e4. /home/runner/work/gh-aw/gh-aw/actions/setup/js/dismiss_pull_request_review.cjs now enriches non-404 getReview failures with the review_id and owner/repo#pull_request_number context before rethrowing, so fatal safe-output logs stay actionable.

expect(result.reason).toContain("review no longer exists");
expect(result.review_id).toBe(123);
expect(mockDismissReview).not.toHaveBeenCalled();
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No test asserts that non-404 errors from getReview (e.g. 500 or transient network failures) still propagate as failures rather than being swallowed.

💡 Details

The new test only exercises the happy path for the 404 no-op. There is no negative test verifying that a non-404 error (e.g. status: 500 or an error without a status field) still causes handler to return success: false (or throw, per the outer catch). Without this guard test, a future refactor that widens the getReviewError?.status === 404 check (e.g. to >= 400 or a truthy check) could silently convert real failures into false skipped: true no-ops, and CI wouldn't catch the regression.

Suggested addition:

it("still fails when getReview returns a non-404 error", async () => {
  const serverError = Object.assign(new Error("Internal Server Error"), { status: 500 });
  mockGetReview.mockRejectedValueOnce(serverError);

  const result = await handler({
    type: "dismiss_pull_request_review",
    review_id: 123,
    justification: "...",
  });

  expect(result.success).toBe(false);
  expect(mockDismissReview).not.toHaveBeenCalled();
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6aa73e4. I added a non-404 regression in /home/runner/work/gh-aw/gh-aw/actions/setup/js/dismiss_pull_request_review.test.cjs that keeps getReview 500s fatal and verifies dismissReview is not called.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please give this PR a finishing pass and run the pr-finisher skill.

This PR currently looks unblocked from the compact triage view, so please:

  • confirm the stale review_id 404 no-op behavior is covered by tests,
  • verify any edge-case error paths are documented clearly, and
  • re-run formatting/checks as needed before pushing any final polish.

If everything is already complete, summarize readiness in the PR and proceed with any last small fixes.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 15.2 AIC · ⌖ 8.57 AIC · ⊞ 8.2K ·
Comment /souschef to run again

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please give this PR a finishing pass and run the pr-finisher skill.

This PR currently looks unblocked from the compact triage view, so please:...

Finished in 6aa73e4.

  • ✅ Reviews — addressed the in-scope review feedback with a small follow-up: the 404 no-op test now covers pull_request_number and repo, and non-404 getReview failures now preserve fatal behavior with clearer context.
  • ✅ Checks (local) — make fmt, make lint, make test-unit, make test, targeted Vitest for /home/runner/work/gh-aw/gh-aw/actions/setup/js/dismiss_pull_request_review.test.cjs, and make agent-report-progress all passed.
  • ❓ Checks (CI) — last-known PR checks were green before this push, but CI on 6aa73e4 is stale/unverified until a maintainer re-triggers it. Prior failures inspected: none on the relevant CJS workflow run.
  • ✅ Mergeable — PR is open, not draft, and currently reports a clean merge state.

Hand-off: CI must be re-triggered by a maintainer before merge.

Copilot AI requested a review from gh-aw-bot August 2, 2026 11:30
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please give this PR a finishing pass and run the pr-finisher skill.

This PR looks close to done from triage:

  • branch refresh was requested,
  • no failed checks are currently listed in compact triage,
  • please verify the follow-up commit fully addresses the minor review suggestions and leaves the PR ready for maintainers.

After that, run the pr-finisher skill.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 31.4 AIC · ⌖ 8.75 AIC · ⊞ 8.3K ·
Comment /souschef to run again

Copilot AI commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please give this PR a finishing pass and run the pr-finisher skill.

This PR looks close to done from triage:...

Verified on 879bf63 with no further code changes needed.

  • The branch refresh request is already satisfied by the merge-from-main commit 879bf63.
  • The follow-up fix from 6aa73e4 is still present in /home/runner/work/gh-aw/gh-aw/actions/setup/js/dismiss_pull_request_review.cjs and /home/runner/work/gh-aw/gh-aw/actions/setup/js/dismiss_pull_request_review.test.cjs, including the full 404 no-op shape assertions and the non-404 fatal-path regression.
  • Local validation passed again: make fmt, make lint, make test-unit, make test, and make recompile.
  • Last-known relevant CI runs show no failed jobs; the remaining GitHub Actions review threads already have substantive Copilot replies.

Ready for maintainers pending normal CI/check completion state on the current HEAD.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please give this PR a finishing pass and run the pr-finisher skill.

Current triage signals:

  • no failed checks are listed in compact triage,
  • a branch refresh was requested,
  • previous follow-up comments indicate the 404 stale review-id behavior and tests are already addressed; please confirm the current head is still ready for maintainers.

After that, run the pr-finisher skill.

Generated by 👨🍳 PR Sous Chef

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 7.13 AIC · ⌖ 5.02 AIC · ⊞ 8.3K ·
Comment /souschef to run again

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

PR Triage

  • Category:
  • Risk:
  • Priority: (score: 56/100)
    • Impact: 26/50, Urgency: 10/30, Quality: 20/20
  • Recommended action:

Automated triage — see full report issue for details.

Structured data:

{
  "action": "auto_merge",
  "category": "bug",
  "pr_number": 49745,
  "risk": "low"
}

Generated by 🔧 PR Triage Agent · auto · 73.4 AIC · ⌖ 3.47 AIC · ⊞ 8K ·

@pelikhan
pelikhan merged commit 9606860 into main Aug 2, 2026
1 of 2 checks passed
@pelikhan
pelikhan deleted the copilot/aw-failures-dismiss-pull-request-review branch August 2, 2026 12:53
Copilot stopped work on behalf of gh-aw-bot due to an error August 2, 2026 12:53
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.84.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[aw-failures] dismiss_pull_request_review 404 on stale review_id hard-fails safe_outputs job

4 participants